import { Point3 } from '@/types';
import { Line } from '@react-three/drei';
import { isEqual, uniqWith } from 'lodash-es';
import { Fragment, useRef } from 'react';
import { Group, Line3, MathUtils, Vector3 } from 'three';
import { Word } from '../Word';

const lineOffset = 20;
const tickLen = 10;
const tickLenHalf = tickLen / 2;

interface Tick {
  position: Point3;
  text: string;
  direction?: 'start' | 'end';
}

interface Props {
  start: Point3;
  end: Point3;
  ticks?: Tick[];
}

export function Mark(props: Props) {
  const { start, end } = props;
  // const ticks = props.ticks ?? [];
  const ticks = uniqWith(props.ticks, isEqual);

  const [startVector3, endVector3] = [start, end].map((p) => {
    return new Vector3(...p);
  });
  const baseLine3 = new Line3(startVector3, endVector3);

  const baseLineDirectionVector3 = baseLine3.delta(new Vector3()).normalize();

  const tickDirectionVector3 = baseLineDirectionVector3
    .clone()
    .applyAxisAngle(new Vector3(0, 0, 1), MathUtils.degToRad(90));

  const groupRef = useRef<Group>(null);

  return (
    <group
      ref={groupRef}
      position={tickDirectionVector3.clone().multiplyScalar(lineOffset)}
    >
      <Line points={[start, end]} color={'red'} lineWidth={1} dashed={false} />
      {ticks?.map((tick) => {
        const tickPositionVector3 = new Vector3(...tick.position);
        const startVector3 = tickPositionVector3
          .clone()
          .addScaledVector(tickDirectionVector3, -tickLen);
        const endVector3 = tickPositionVector3
          .clone()
          .addScaledVector(tickDirectionVector3, tickLen);

        return (
          <Fragment key={tick.position.toString()}>
            <Line
              points={[startVector3, endVector3]}
              color={'green'}
              lineWidth={1}
              dashed={false}
            />
            {tick.direction && (
              <Line
                points={[
                  endVector3,
                  endVector3
                    .clone()
                    .addScaledVector(
                      tick.direction === 'start'
                        ? baseLineDirectionVector3.clone().negate()
                        : baseLineDirectionVector3.clone(),
                      tickLenHalf,
                    ),
                ]}
                color={'green'}
                lineWidth={1}
                dashed={false}
              />
            )}
            <Word
              fontSize={10}
              color={'red'}
              position={endVector3
                .clone()
                .addScaledVector(tickDirectionVector3, 15)}
            >
              {tick.text}
            </Word>
          </Fragment>
        );
      })}
    </group>
  );
}
